<template>
	<u-upload :maxCount="1" name='tx' :fileList='fileList' :deletable='false' :maxSize="1*1024*1024"
		:previewFullImage='false' :previewImage='true'  @afterRead='afterRead'
		 @oversize='oversize'>
		<!-- 注意:previewImage需要设置成true，否则会看不到头像。previewFullImage应该设置成false，
	否则，第一次上传头像后，再次点击头像，就会显示全屏的放大预览图。关闭previewFullImage后，虽然再次点击头像不会显示预览图，
	但再次上传功能也失效了。所以要把width和height设置成0，不显示预览区域。但这样又会导致上传头像后，头像区域大小为0了。
	所以需要在头像的父窗口中添加css，设置大小。-->
		<u-avatar slot='' :src="pic" shape="circle" size="80"></u-avatar>
	</u-upload>
</template>

<script>
	let access_token; //由于好多地方都要使用这个token，因此，做一个全局的参数
	export default {
		name: "ossUploadPic",
		data() {
			return {
				pic: '',
				fileList: [],
				ossKey: '' //上传到阿里云上的文件名
			};
		},
		methods: {
			oversize(event) {
				console.log(event);
			},
			// 新增图片
			async afterRead(event) {
				let lists = event.file;
				this.fileList.push({ //push后，fileList是一个有一个元素的数组
					...lists,
					//... 运算符， 是ES6里一个新引入的运算法， 也叫展开/收集运算符
					//例1（展开）：
					//let a = [1,2,3];let b = [0, ...a, 4]; 那b的结果就是：[0,1,2,3,4]
					//例2（收集）：
					//let a = [1,2,3];let [b, ...c] = a;则b的结果是1，c的结果是[2,3]
					//例3（为数组增加新成员）：
					//const peoples = ["jone", "jack"];
					//const mrFan = "吴亦凡";
					//const all = [...peoples, mrFan];
					//console.log(all); 结果是： ["jone", "jack", "吴亦凡"]
					//例4（为对象增加新属性）：
					//const obj = { name: 'jack', age: 30 }
					//const result = { ...obj, sex: '男', height: '178cm' }
					//console.log(result); // {name: "jack", age: 30, sex: "男", height: "178CM"}
					status: 'uploading', //这个状态将显示loading符号
					message: '上传中' //loading过程中显示的提示文字
				})
				//需要注意是，在H5和小程序（以及APP）中，这个lists的内容有所不同。
				//H5会得到
				/* 
				name: "cdjhh_logo.jpg"
				size: 23889
				thumb: "blob:http://localhost:8080/5c2b104e-57f2-4b63-a798-96a99f6d143d"
				type: "image"
				url: "blob:http://localhost:8080/5c2b104e-57f2-4b63-a798-96a99f6d143d" 
				*/
				//小程序会得到：
				/*  size: 23889
					thumb: "http://tmp/PSDocq3Wr6PP96cb9627d599161899f986bbcc992e94.jpg"
					type: "image"
					url: "http://tmp/PSDocq3Wr6PP96cb9627d599161899f986bbcc992e94.jpg"
				*/
				//APP会得到：
				/* 
				"size": 44570,
				"type": "image",
				"url": "file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/doc/uniapp_temp/compressed/1643529240956_IMG_20220130_155333.jpg",
				"thumb": "file:///storage/emulated/0/Android/data/io.dcloud.HBuilder/apps/HBuilder/doc/uniapp_temp/compressed/1643529240956_IMG_20220130_155333.jpg"
				*/
				//首先获取文件的扩展名
				// #ifdef H5
				const filename = lists.name;
				// #endif
			 // #ifndef H5
				const filename = lists.thumb;
				// #endif
				const ext = filename.slice(filename.lastIndexOf('.')).toLowerCase(); //slice是用于返回数组（字符串）中指定起始值至结束值之间的元素（内容），如果没有结束值，则返回起始值以后的所有元素
				const allowExt = ['.jpg', '.jpeg', '.png', '.gif'];
				if (allowExt.indexOf(ext) <= -1) {
					uni.$u.toast('只能上传' + allowExt.join('、') + '文件');
					this.fileList.pop();
					return;
				}
				const result = await this.uploadFilePromise(lists.thumb, ext);
				let item = this[`fileList`][0];
				this[`fileList`].splice(0, 1, Object.assign(item, {
					status: 'success',//关闭图片loading状态
					message: ''
				}))
				
				
				if (result) { //如果上传成功，返回空，否则会返回具体的错误信息
					uni.$u.toast('图片上传失败');
				} else {										
					//上传成功后，调用接口更新服务器上的头像，然后更新缓存。
					//这个接口文档是PATCH类型，但经过测试，实际上是POST类型。如果真的是PATCH请求，需要用POST来模拟，
					//只需要在参数中多添加一个_method:'PATCH'即可。					
					await uni.$u.http.post('/api/user/avatar', {
						avatar: this.ossKey
					}, {
						header: {
							Authorization: 'bearer ' + access_token
						}
					});
					//头像更新成功后，获取个人信息。
					const token = uni.getStorageSync('access_token');
					const res = await uni.$u.http.get('/api/user',{header:{Authorization:'bearer ' + token}});
					uni.setStorageSync('userinfo',res);
					uni.$u.toast('图片上传成功');
					this.pic = res.avatar_url; //更新本地头像
					//头像上传成功事，需要把预览区域的图像删除，以显示远程真正的头像。
					//直接从上传列表中删除文件即可。否则，将一直显示这个预览图像，无法再次点击重新上传新的头像
					this.fileList.pop();
				}
			},
			uploadFilePromise(url, extName) {
				return new Promise(async (resolve, reject) => {
					//API提供的文件上传，是上传阿里云服务器，这个上传的方式，首先是通过接口 /api/auth/oss/token 获取token，
					//然后再通过此token中的相应的参数去实现文件的上传，具体内容请参考api文档的说明。
					//返回的token中，我们要用到以下内容：accessid、host、policy、signature								
					let res = await uni.$u.http.get('/api/auth/oss/token', {
						header: {
							Authorization: 'bearer ' + access_token
						}
					});
					const filename = uni.$u.guid(20) + extName; //这个是上传后的文件名，做唯一处理。
					this.ossKey = filename;
					uni.uploadFile({
						url: res.host,
						filePath: url,
						name: 'file',
						formData: {
							key: this.ossKey, //这5个参数，是阿里云存储上传时需要的参数，具体内容请参数api文档
							policy: res.policy,
							OSSAccessKeyId: res.accessid, //注意，api返回的值是accessid
							signature: res.signature,
							success_action_status: '200'
						},
						success: (res) => {
							setTimeout(() => {
								resolve(res.data)
							}, 1000)
						}
					});
				})
			}
		},
		created() {
			const userinfo = uni.getStorageSync('userinfo');
			this.pic = userinfo.avatar_url;
			access_token = uni.getStorageSync('access_token');
		}
	}
</script>

<style>

</style>
